package com.hengpeng.itfin.service.assign.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.hengpeng.common.exception.ServiceResult;
import com.hengpeng.common.persist.query.DynamicQuery;
import com.hengpeng.common.util.DateTimeUtil;
import com.hengpeng.common.util.MoneyUtil;
import com.hengpeng.itfin.service.assign.AssignService;
import com.hengpeng.itfin.service.impl.BaseServiceImpl;
import com.hengpeng.itfinbase.constants.RespCodeConstants;
import com.hengpeng.itfinbase.constants.RespCodeConstants.CommonCode;
import com.hengpeng.itfinbase.en.TradeMode;
import com.hengpeng.itfinbase.en.TransType;
import com.hengpeng.itfinbase.message.partner.CreditAssignRequest;
import com.hengpeng.itfinbase.message.partner.CreditAssignResponse;
import com.hengpeng.itfinbase.persist.BorrowInfo;
import com.hengpeng.itfinbase.persist.CreditAssign;
import com.hengpeng.itfinbase.persist.CreditAssign.AssignStatus;
import com.hengpeng.itfinbase.persist.InvestInfo;
import com.hengpeng.itfinbase.persist.UserInfo;

@Service
@Lazy
@Transactional
public class AssignServiceImpl extends BaseServiceImpl implements AssignService {
    @Override
    public CreditAssignResponse createAssign(CreditAssignRequest reqMsg) {
        CreditAssignResponse response = new CreditAssignResponse();
        InvestInfo invest = serviceFactory.getPersistService().get(InvestInfo.class, reqMsg.getInvestInfoId());
        BorrowInfo borrowInfo = serviceFactory.getPersistService().get(BorrowInfo.class, invest.getBorrowInfoId());
        CreditAssign creditAssign = new CreditAssign();
        creditAssign.setBorrowInfoId(borrowInfo.getId());
        creditAssign.setBorrowName(borrowInfo.getBorrowName());
        creditAssign.setBorrowRate(borrowInfo.getBorrowRate());
        creditAssign.setBorrowMoney(borrowInfo.getBorrowMoney());
        creditAssign.setRepaymentType(borrowInfo.getRepaymentType());
        creditAssign.setInvestInfoId(invest.getId());
        creditAssign.setInvestMoney(invest.getInvestMoney());
        creditAssign.setSellUserId(invest.getNowOwnUserId());
        creditAssign.setSellTrustAccountId(invest.getNowOwnUserTrustAccountId());
        creditAssign.setStatus(CreditAssign.AssignStatus.PUBLISHED);
        creditAssign.setAssignDuration(reqMsg.getAssign_duration());// 债权认购期限
        creditAssign.setCreateTime(new Date());
        creditAssign.setUpdateTime(new Date());
        creditAssign = serviceFactory.getPersistService().save(creditAssign);
        if (creditAssign.getId() == null) {
            response.setRespCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            response.setRespDesc(RespCodeConstants.CommonCode.TRANS_FAIL_MSG);
        }
        return response;
    }

    @Override
    public void packCreditAssing(CreditAssignRequest reqMsg) {
        CreditAssign creditAssign = serviceFactory.getPersistService().get(CreditAssign.class,
                Long.parseLong(reqMsg.getOrdId()));
        creditAssign.setStatus(AssignStatus.ASSIGNING);
        creditAssign.setSellMoney(MoneyUtil.convertLongYuanToFen(Double.parseDouble(reqMsg.getCreditAmt())));
        creditAssign.setLeftPlanNum(reqMsg.getLeftPlanNum());
        creditAssign.setLeftMoney(reqMsg.getLeftMoney());
        creditAssign.setBuyUserId(Long.parseLong(reqMsg.getBuyUserId()));
        creditAssign.setBuyTrustAccountId(reqMsg.getBuyCustId());
        creditAssign.setBuyMoney(MoneyUtil.convertLongYuanToFen(Double.parseDouble(reqMsg.getCreditDealAmt())));
        creditAssign.setRepaymentedMoney(reqMsg.getRepaymentedMoney());
        creditAssign.setFeeMoney(MoneyUtil.convertLongYuanToFen(Double.parseDouble(reqMsg.getFee())));
        serviceFactory.getPersistService().update(creditAssign);
    }

    /**
     * <pre>
     * 失败：
     * 1,更新债权转让信息状态为：发布中
     * 成功:
     * 1,更新债权转让信息状态为成功
     * 2,更新投标信息的当前债权人
     * 3,添加出让人的资金流水
     * 4,添加承接人的资金流水
     * </pre>
     */
    @Override
    public ServiceResult<String> dealAssignResult(CreditAssignResponse response) {
        ServiceResult<String> result = new ServiceResult<String>();
        if (response == null || !CommonCode.TRANS_SUC.equals(response.getRespCode())) {
            result.setIsSuccess(false);
            // 失败
            CreditAssign creditAssign = serviceFactory.getDaoFactory().getCommonDao()
                    .lockObject(CreditAssign.class, Long.parseLong(response.getOrdId()));
            if (creditAssign != null && creditAssign.getStatus().equals(CreditAssign.AssignStatus.ASSIGNING)) {
                creditAssign.setStatus(CreditAssign.AssignStatus.PUBLISHED);// 回退状态为：发布中
                creditAssign.setUpdateTime(new Date());
                serviceFactory.getDaoFactory().getCommonDao().updateEntity(creditAssign);
            } else {
                result.setMessage(RespCodeConstants.CommonCode.TRANS_FAIL);
                result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL_MSG);
            }
            return result;
        } else if (CommonCode.TRANS_SUC.equals(response.getRespCode())) {
            // 成功
            CreditAssign creditAssign = serviceFactory.getDaoFactory().getCommonDao()
                    .lockObject(CreditAssign.class, Long.parseLong(response.getOrdId()));
            if (creditAssign != null && creditAssign.getStatus().equals(AssignStatus.ASSIGNING)) {
                creditAssign.setStatus(CreditAssign.AssignStatus.ASSIGNSUCCESS);
                creditAssign.setUpdateTime(new Date());
                creditAssign.setAssignSuccessTime(new Date());
                serviceFactory.getDaoFactory().getCommonDao().updateEntity(creditAssign);

                UserInfo buyUserInfo = serviceFactory.getPersistService().get(UserInfo.class,
                        creditAssign.getBuyUserId());
                InvestInfo investInfo = serviceFactory.getDaoFactory().getCommonDao()
                        .getEntity(InvestInfo.class, creditAssign.getInvestInfoId());
                investInfo.setNowOwnUserId(creditAssign.getBuyUserId());
                investInfo.setNowOwnUserName(buyUserInfo.getRealName());
                investInfo.setNowOwnUserTrustAccountId(creditAssign.getBuyTrustAccountId());
                investInfo.setUpdateTime(new Date());
                serviceFactory.getDaoFactory().getCommonDao().updateEntity(investInfo);
                Long fee = MoneyUtil.convertLongYuanToFen(Double.parseDouble(response.getFee()));
                serviceFactory.getAccountService().changeAccountMoney(creditAssign.getSellUserId(),
                        creditAssign.getBuyMoney(), 0l, 0l, 0l, TransType.CREDITASSIGN, TradeMode.ADD,
                        creditAssign.getId().toString(), "债权转让收入");// 添加出让人资金流水

                // changeAccountMoney(creditAssign.getSellUserId(),
                // creditAssign.getBuyMoney(), TransType.CREDITASSIGN,
                // TradeMode.ADD,
                // creditAssign.getId().toString(), "债权转让收入");

                serviceFactory.getAccountService().changeAccountMoney(creditAssign.getSellUserId(), fee, 0l, 0l, 0l,
                        TransType.CREDITASSIGN_FEE, TradeMode.SUBTRACT, creditAssign.getId().toString(), "债权转让手续费扣款");

                // changeAccountMoney(creditAssign.getSellUserId(), fee,
                // TransType.CREDITASSIGN_FEE, TradeMode.SUBTRACT,
                // creditAssign.getId().toString(), "债权转让手续费扣款");// 债权转让手续费扣款

                serviceFactory.getAccountService().changeAccountMoney(creditAssign.getBuyUserId(),
                        creditAssign.getBuyMoney(), 0l, 0l, 0l, TransType.CREDITASSIGN, TradeMode.SUBTRACT,
                        creditAssign.getId().toString(), "投资人债权承接付款");// 添加承接人的资金流水
                // changeAccountMoney(creditAssign.getBuyUserId(),
                // creditAssign.getBuyMoney(), TransType.CREDITASSIGN,
                // TradeMode.SUBTRACT,
                // creditAssign.getId().toString(), "投资人债权承接付款");

                result.setCode(RespCodeConstants.CommonCode.TRANS_SUC);
                result.setMessage(RespCodeConstants.CommonCode.TRANS_SUC_MSG);
                result.setIsSuccess(true);
            } else {
                result.setIsSuccess(true);
                result.setMessage(RespCodeConstants.CommonCode.TRANS_SUC_MSG);
                result.setCode(RespCodeConstants.CommonCode.TRANS_SUC);
            }
        }
        return result;
    }

    @Override
    public List<CreditAssign> getCreditAssigns(AssignStatus[] status) {
        DynamicQuery query = new DynamicQuery(CreditAssign.class);
        if (status != null && status.length > 0) {
            query.inArray("status", status);
        }
        return serviceFactory.getPersistService().findByDynamicQuery(CreditAssign.class, query);
    }

    @Override
    public void endAssign(List<CreditAssign> creditAssigns) {
        try {
            if (creditAssigns != null && creditAssigns.size() > 0) {
                List<Future<Long>> rtList = new ArrayList<Future<Long>>();
                ExecutorService execute = Executors.newFixedThreadPool(creditAssigns.size());
                for (final CreditAssign iv : creditAssigns) {
                    Future<Long> submit = execute.submit(new Callable<Long>() {
                        public Long call() {
                            try {
                                serviceFactory.getAssignService().doEndAssign(iv);
                            } catch (Throwable e) {
                                logger.error("债权转让过期截止检查线程异常", e);
                            }
                            return 0L;
                        }
                    });
                    rtList.add(submit);
                }
                execute.shutdown();
                for (Future<Long> future : rtList) {
                    future.get();
                }
            }
        } catch (Throwable e) {
            logger.error("债权转让过期截止检查线程异常", e);
        }
    }

    @Override
    public void doEndAssign(CreditAssign creditAssign) {
        Date time = DateTimeUtil.addDate(creditAssign.getCreateTime(), creditAssign.getAssignDuration());
        if (time.getTime() < System.currentTimeMillis()) {
            creditAssign.setStatus(AssignStatus.ASSIGNFAIL);
            creditAssign.setUpdateTime(new Date());
            serviceFactory.getPersistService().update(creditAssign);
        }
    }
}
